;;;
;;; TYPES
;;;

(define (evaluate exp)
  (eval (parse exp) '()))

(define the-array-var (parse 'array))

(import-types (object object-type)
	      (float float-type)
	      (single-float single-float-type)
	      (integer integer-type)
	      (short short-type)
	      (byte byte-type)
	      (signed-byte signed-byte-type)
	      (boolean boolean-type)
	      (character character-type)
	      (string string-type)
	      (void void-type)
	      (type type-type))

;;;
;;; NEW AND NEW-ARRAY
;;;

(%import 'new
	 (new new-operator)
	 (new new-operator-type))
(%import 'new-array
	 (new new-array-operator)
	 (new new-array-operator-type))


;;;
;;; OPERATORS
;;;

(define index-operator "[")

(let ((a the-arithmetic-type)
      (binary-int (proc (integer integer) integer))
      (object-comp (proc (object object) boolean))
      (numeric-comp (proc (float float) boolean))
      (bitwise-or bitwise-ior)
      (as identity)
      (and #f)				;weird kluge
      (or #f))
  (import-operators
   (+ "+" 0 a)
   (string-append "+" 0 (proc (string string) string))
   (- "-" 0 a)
   (/ "/" 0 a)
   (* "*" 0 a)
   (quotient "/" 2 binary-int)
   (modulo "%" 2 binary-int)
   (eq? "==" 2 object-comp)
   (= "==" 2 numeric-comp)
   (> ">" 2 numeric-comp)
   (< "<" 2 numeric-comp)
   (>= ">=" 2 numeric-comp)
   (<= "<=" 2 numeric-comp)
   (arithmetic-shift "<<" 2 binary-int)
   (vector-ref index-operator 2 (new vector-ref-type))
   (is? " is " 0 (proc (object-type type-type) boolean-type))
   (as " as " 0 (new as-operator-type))
   (bitwise-and "&" 2 binary-int)
   (bitwise-or "|" 2 binary-int)
   (bitwise-not "~" 2 (proc (integer) integer))
   (and "&&" 0 the-boolean-operator-type)
   (or "||" 0 the-boolean-operator-type)
   (not "!" 4 (proc (boolean) boolean))
   (zero? "!" 0 (proc (float) boolean))))

;;;;
;;;; COLLECTION CLASS STUFF
;;;;

(import-fields (length "Length"
			(proc (object) integer)))

(import-methods (copy-into "CopyTo"
			   (proc (object object integer) void)))

(define-imported-class (ienumerator "System.Collections.IEnumerator") object
  (define current "Current" (public property) object)
  (define (move-next) (public) boolean)
  (define (reset) (public) void))

(define-imported-class (ienumerable "System.Collections.IEnumerable") object
  (define (get-enumerator) (public) ienumerator))

(define-imported-class (icollection "System.Collections.ICollection") ienumerable
  (define (copy-to (object a) (integer index)) (public) void)
  (define count "Count" (public property) integer))

(define-imported-class (ilist "System.Collections.IList") icollection
  (define (%index-of "IndexOf" (object o)) (public) object)
  (define (add (object x)) (public) integer)
  (define item "Item" (public) (array object)))

(import-static (copy-subarray "System.Array.Copy"
			      (proc (object integer object integer integer)
				    void)))


(define-imported-class (stack "System.Collections.Stack") icollection
  (define (push (object o)) (public) void)
  (define (pop) (public) object))

;;;;
;;;; MATH
;;;;

(let ((t (proc (float) float)))
  (import (abs "Math.Abs" t)
	  (sin "Math.Sin" t)
	  (cos "Math.Cos" t)
	  (tan "Math.Tan" t)))

;;;;
;;;; PRIMITIVE DATATYPES
;;;;

;;;
;;; CHARS
;;;

(let ((predicate (proc (character) boolean)))
  (import-static
   (crap-char? "Kluge.IsCrapChar" predicate)
   (digit? "System.Char.IsDigit" predicate)
   (whitespace? "System.Char.IsWhiteSpace" predicate)
   (separator? "System.Char.IsSeparator" predicate)
   (symbol-char? "System.Char.IsSymbol" predicate)
   (punctuation? "System.Char.IsPunctuation" predicate)
   (control? "System.Char.IsControl" predicate)
   (number-char? "System.Char.IsNumber" predicate)
   (letter? "System.Char.IsLetter" predicate)
   (letter-or-digit? "System.Char.IsLetterOrDigit" predicate)))

(import-static (integer->character "(char)" (proc (integer-type) character-type)))

;;;;
;;;; I/O
;;;;

(define-imported-class stream object
  (define (flush) (public) void))

(define-imported-class (text-reader "System.IO.TextReader") stream
  (define (peek) (public) integer)
  (define (read) (public) integer)
  (define (read-line) (public) string))

(define-imported-class (text-writer "System.IO.TextWriter") stream
  (define (write (object thing)) (public) void)
  (define (write-line (object thing)) (public) void))

(define-imported-object in "Console.In" text-reader)
(define-imported-object out "Console.Out" text-writer)
(define-imported-object err "Console.Err" text-writer)

(define-imported-class (memory-stream "System.IO.MemoryStream") stream)

;;;;
;;;; COLLECTIONS
;;;;

(import-static
 (to-string "System.Convert.ToString"
	    (proc (object) string))
 (array->string "new string"
		(proc ((array-type character-type)) string))
 (string->integer "Meta.Utilities.ToInt32"
		  (proc (string) integer))
 (string->float "Meta.Utilities.ToDouble"
		(proc (string) float)))

;;;
;;; STRING
;;;

(let ((t (proc (string '(array character)) integer)))
  (%import 'index-of-any
	   (new method "IndexOfAny" '() integer-type)
	   t))

(let ((string-ref #f))
  (import-operators (string-ref index-operator 2
				(proc (string integer) character))))

;;;
;;; ARRAYLIST
;;;

(define-imported-class (array-list "System.Collections.ArrayList") ilist
  (define (to-array) (public) (array object)))

;;;
;;; HASHTABLES
;;;

(define-imported-class (hashtable "System.Collections.Hashtable") object)
(define hashtable (evaluate 'hashtable))
(let ((gethash #f))
  (import-operators
   (gethash index-operator
	    2
	    (proc (hashtable object-type)
		  object-type))))

;;;;
;;;; EXCEPTION HANDLING
;;;;

(define-imported-class (exception (string message))  object)
(define exception (evaluate 'exception))
(import-static (throw "throw" (proc (exception) void)))

;;;;
;;;; FORMS
;;;;

(define-imported-class (form) object
  (define (show) (public virtual) void)
  (define (show-dialog) (public virtual) void))

;;;;
;;;; REFLECTION
;;;;
(define-imported-class (clr-type "Type") object
  (define (type-name) (public) string))

(define clr-type (evaluate 'clr-type))

(import (type->clr-type "typeof" (proc (type) clr-type)))

(define-imported-class (member-info "System.Reflection.MemberInfo") object
  (define member-static? "IsStatic" (public) boolean)
  (define declaring-type "DeclaringType" (public) clr-type))

(define-imported-class (parameter-info "System.Reflection.ParameterInfo")
  object
  (define parameter-type (public) clr-type)
  (define parameter-name "Name" (public) string))

(define-imported-class (constructor-info "System.Reflection.ConstructorInfo")
  member-info
  (define (invoke-constructor "Invoke"
			      ((array object) args)) (public) object))

(define-imported-class (field-info "System.Reflection.FieldInfo")
  member-info
  (define (get-field-value "GetValue" (object o)) (public) object))

(define-imported-class (property-info "System.Reflection.PropertyInfo")
  member-info
  (define (get-property-value "GetValue" (object o) ((array object) args)) (public) object))

(define-imported-class (method-info "System.Reflection.MethodInfo")
  member-info
  (define (invoke-method "Invoke" (object obj) ((array object) args)) (public) object)
  (define (get-parameters) (public) (array parameter-info)))

(define-imported-class (clr-type "Type") object
  (define (is-instance-of-type (object o)) (public) 
    boolean)
  (define (get-constructor ((array clr-type) types))
    (public) constructor-info)
  (define (get-method (string name)) (public) method-info)
  (define (get-field (string name)) (public) field-info)
  (define (get-property (string name)) (public) property-info)
  (define (invoke-member (string name)
			 (integer binding-flags)
			 (object binder)
			 (object target)
			 ((array object) arglist))
    (public static) object)
  (define type-name "Name" (public) object)
  (define (get-type-array ((array object) objects)) (public static)
    (array clr-type)))
  
(import-methods (type-of "GetType"
			 (proc (object) clr-type)))

(import-static (type-named "Type.GetType"
			   (proc (string) clr-type)))

(import-enumeration "BindingFlags"
		    (public "Public")
		    (static "Static")
		    (instance "Instance")
		    (invoke-method "InvokeMethod")
		    (get-field "GetField")
		    (set-field "SetField")
		    (get-property "GetProperty")
		    (set-property "SetProperty"))

;;;
;;; GRAPHICS
;;;

(define-imported-class (pen "System.Drawing.Pen") object)
(define-imported-class (color "System.Drawing.Color") object)
(define-imported-class (point "System.Drawing.Point") object)

(define-imported-class (graphics "System.Drawing.Graphics") object
  (define (draw-line (pen p) (point start) (point end))
    (public) void))

(define-imported-class (image "System.Drawing.Image") object)
(define-imported-class (bitmap "System.Drawing.Bitmap"
			       (string filename))
  image
  (define (get-pixel (integer x) (integer y))
    (public) color)
  (define (set-pixel (integer x) (integer y) (color p))
    (public) void))
(define-imported-class (metafile "System.Drawing.Imaging.Metafile"
				 (stream s)) image)
